package net.chrisrichardson.ec2deployer.cluster

import net.chrisrichardson.ec2deployer.core.EC2Server
import net.chrisrichardson.ec2deployer.core.CloudManager
import net.chrisrichardson.ec2deployer.core.ProcessExecutionException
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory


abstract class AbstractTier implements Tier {
    long id
    CloudManager ec2
    def monitoredState
    boolean started = false
    Log logger = LogFactory.getLog(getClass())

    protected AbstractTier() {}
    
    protected AbstractTier(CloudManager ec2) {
        this.ec2 = ec2
    }

    void waitUntilRunning(Set waitedFor) {
        waitUntilRunning(servers, waitedFor)
    }

    void waitUntilRunning(List<EC2Server> servers, Set waitedFor) {
        for (EC2Server server : servers) {
            if (!waitedFor.contains(server)) {
                waitedFor.add server
                server.waitUntilRunning()
            }
            runTierStartUpScript(server)
        }
    }

    void runTierStartUpScript(EC2Server server) {
        String prefix = getClass().simpleName
        prefix = prefix.substring(0,1).toLowerCase() + prefix.substring(1)
        runBuiltinStartupScript(server, prefix)
        runUserSpecifiedStartupScript(server, prefix)
    }

    private def runUserSpecifiedStartupScript(EC2Server server, String prefix) {
        String propertyName = prefix + ".startupScript"
        if (ec2.awsProperties.exists(propertyName)) {
            String script = ec2.awsProperties.getProperty(propertyName)
            server.executeScript script
        }
    }

    void runBuiltinStartupScript(EC2Server ec2Server, String scriptPrefix) {
        URL resource = getClass().getResource("/scripts/startup/${scriptPrefix}.sh");
        if (resource)
            ec2Server.executeScriptText (resource.text)

    }

   	boolean isExpandable() {
   	  false
   	}
   	
    boolean isShrinkable() {
      false
    }

    void start() {
        if (!started)
            performStart()
        started = true
    }

    void stop() {
        performStop()
        started = false
    }

    protected abstract void performStart()

    protected void performStop() {

    }

    def phase(String label, Closure closure) {
        try {
            closure.call();
        } catch (ProcessExecutionException e) {
            logger.error("execution error", e)
            throw new TierExecutionException(this, label, e)
        }

    }
}